#include "xmlhandler.h"
#include <fstream>
#include <iostream>
using namespace std;
XMLHandler::XMLHandler() {
}
XMLHandler::~XMLHandler() {
}
void XMLHandler::setView(IChessView * view , Board * board) {
	myView = view;
	myBoard = board;
}
void XMLHandler::saveGame(std::string filename) {
	UpdateCurrentXML();
	const char *cstr = filename.c_str();
	ofstream file;
	file.open(cstr);
	file << currentGameXML;
	file.close();
}
void XMLHandler::addToPiecesOnBoard(string type, string color,int r, int c) {
	Color cor = (color == "black") ? black : white;
	if(type == "pawn") {
		myBoard->piecesOnBoard.push_back(new Pawn(r,c,cor));
	}
	if(type == "bishop") {
		myBoard->piecesOnBoard.push_back(new Bishop(r,c,cor));
	}
	if(type == "king") {
		myBoard->piecesOnBoard.push_back(new King(r,c,cor));
	}
	if(type == "queen") {
		myBoard->piecesOnBoard.push_back(new Queen(r,c,cor));
	}
	if(type == "rook") {
		myBoard->piecesOnBoard.push_back(new Rook(r,c,cor));
	}
	if(type == "knight") {
		myBoard->piecesOnBoard.push_back(new Knight(r,c,cor));
	}
}
void XMLHandler::loadGame(std::string filename) {
	const char *cstr = filename.c_str();
	pugi::xml_document doc;
	if (!doc.load_file(cstr)) {
		myView->WriteMessageArea("LOADING ERROR");
		return;
	}
	pugi::xml_node board = doc.child("chessgame").child("board");
	//code_traverse_iter
	for (pugi::xml_node_iterator it = board.begin(); it != board.end(); ++it) {
		std::string type = it->attribute("type").value();
		std::string color = it->attribute("color").value();
		int row = it->attribute("row").as_int();
		int col = it->attribute("column").as_int();
		addToPiecesOnBoard(type,color,row,col);
	}
	pugi::xml_node moves = doc.child("chessgame").child("history");
	for (pugi::xml_node_iterator it = moves.begin(); it != moves.end(); ++it) {
		pugi::xml_node startPiece = it->first_child();
		pugi::xml_node endPiece = startPiece.next_sibling();
		pugi::xml_node killPiece = endPiece.next_sibling();
		Move addThis = addPieces(startPiece,endPiece,killPiece);
		myBoard->moveHistory.push_back(addThis);
	}
	//myView->WriteMessageArea(message);
}
Move XMLHandler::addPieces(pugi::xml_node start , pugi::xml_node end , pugi::xml_node kill) {
	Move toReturn;
	toReturn.startType = start.attribute("type").value();
	toReturn.color = start.attribute("color").value();
	toReturn.startCol = start.attribute("column").value();
	toReturn.startColint = start.attribute("column").as_int();
	toReturn.startRow = start.attribute("row").value();
	toReturn.startRowint = start.attribute("row").as_int();
	toReturn.endType = end.attribute("type").value();
	toReturn.endCol = end.attribute("column").value();
	toReturn.endColint = end.attribute("column").as_int();
	toReturn.endRow = end.attribute("row").value();
	toReturn.endRowint = end.attribute("row").as_int();
	toReturn.PawnPro = false;
	toReturn.enPassant = false;
	toReturn.castle = false;
	toReturn.kill = false;
	toReturn.PassantRow = 21;
	if(toReturn.endType.compare(toReturn.startType) != 0) {
		toReturn.PawnPro = true;
	}
	std::string a = kill.attribute("type").value();
	if(a.compare("") != 0) {
		toReturn.kill = true;
		toReturn.killType = kill.attribute("type").value();
		if(kill.attribute("color").value() == start.attribute("color").value()) {
			toReturn.castle = true;
		}
		if( kill.attribute("enPassant").as_int() == 1) {
			toReturn.enPassant = true;
			toReturn.PassantRow = toReturn.endRowint;
			toReturn.kill = false;
		}
	}
	return toReturn;
}
void XMLHandler::saveGameAs(std::string filename) {
	saveGame(filename);
}
std::string XMLHandler::addMoveToHistory(Move m) {
	std::string toReturn = "";
	toReturn += "\t\t\t<piece type=\"" + m.startType +"\" ";
	toReturn += "color=\"" + m.color + "\" ";
	toReturn += "column=\"" + m.startCol + "\" ";
	toReturn += "row=\"" + m.startRow + "\"/>\n";
	toReturn += "\t\t\t<piece type=\"" + m.endType +"\" ";
	toReturn += "color=\"" + m.color + "\" ";
	toReturn += "column=\"" + m.endCol + "\" ";
	toReturn += "row=\"" + m.endRow + "\"";
	toReturn += "/>\n";
	if(m.enPassant) {
		m.updateEnPassant();
	}
	if(m.castle) {
		m.updateCastle();
	}
	if(m.kill) {
		toReturn += "\t\t\t<piece type=\"" + m.killType +"\" ";
		std::string enemyColor = (m.color == "white") ? "black" : "white";
		toReturn += "color=\"" + enemyColor + "\" ";
		toReturn += "column=\"" + m.endCol + "\" ";
		toReturn += "enPassant=\"";
		if(m.enPassant) {
			toReturn += "1";
		} else {
			toReturn += "0";
		}
		toReturn += "\" ";
		toReturn += "row=\"" + m.endRow + "\"/>\n";
	}
	return toReturn;
}
void XMLHandler::addHistoryToCurrentXML() {
	std::string move = "\n\t<history>";
	std::vector<Move>::iterator it;
	for ( it = myBoard->moveHistory.begin() ; it < myBoard->moveHistory.end() ; it++) {
		Move m = *it;
		move += "\n\t\t<move>\n";
		move += addMoveToHistory(m);
		move += "\t\t</move>";
	}
	move += "\n\t</history>";
	currentGameXML += move;
}
void XMLHandler::UpdateCurrentXML() {
	currentGameXML = "";
	currentGameXML = "<chessgame>\n";
	addBoardToCurrentXML();
	addHistoryToCurrentXML();
	currentGameXML += "\n</chessgame>\n";
}
void XMLHandler::addPieceType(ChessPiece * p , std::string & piece) {
	switch(p->GetImage()) {
	case(B_PAWN):
	case(W_PAWN):
		piece += "type=\"pawn\" ";
		break;
	case(B_ROOK):
	case(W_ROOK):
		piece += "type=\"rook\" ";
		break;
	case(B_BISHOP):
	case(W_BISHOP):
		piece += "type=\"bishop\" ";
		break;
	default:
		piece += addMorePieceType(p->GetImage());
	}
}
std::string XMLHandler::addMorePieceType(ImageName n) {
	std::string piece = "";
	switch(n) {
	case(B_KING):
	case(W_KING):
		piece += "type=\"king\" ";
		break;
	case(B_QUEEN):
	case(W_QUEEN):
		piece += "type=\"queen\" ";
		break;
	case(B_KNIGHT):
	case(W_KNIGHT):
		piece += "type=\"knight\" ";
		break;
	default:
		piece += "";
	}
	return piece;
}
void XMLHandler::addPieceColor(ChessPiece * p , std::string & piece) {
	switch(p->GetColor()) {
	case(black):
		piece += "color=\"black\" ";
		break;
	case(white):
		piece += "color=\"white\" ";
		break;
	default:
		piece += "";
	}
}
void XMLHandler::addPieceCol(ChessPiece * p , std::string & piece) {
	piece += "column=\"" + MyFunctions::convertInt(p->col) + "\" ";
}
void XMLHandler::addPieceRow(ChessPiece * p , std::string & piece) {
	piece += "row=\"" + MyFunctions::convertInt(p->row) + "\" ";
}
void XMLHandler::addBoardToCurrentXML() {
	std::string piece = "\t<board>";
	std::vector<ChessPiece*>::iterator it;
	for ( it = myBoard->piecesOnBoard.begin() ; it < myBoard->piecesOnBoard.end() ; it++) {
		ChessPiece * p = *it;
		piece += "\n\t\t<piece ";
		addPieceType(p,piece);
		addPieceColor(p,piece);
		addPieceCol(p,piece);
		addPieceRow(p,piece);
		piece += "/>";
	}
	piece += "\n\t</board>";
	currentGameXML += piece;
}
